package fortunata.jspwikiplugins.vpoet;

import com.ecyrd.jspwiki.WikiContext;
import com.ecyrd.jspwiki.plugin.PluginException;
import com.ecyrd.jspwiki.plugin.WikiPlugin;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFNode;
import fortunata.FortunataPlugin;
import fortunata.fswapps.vpoet.Vpoet;
import org.apache.log4j.Logger;

import java.util.Map;


/**
 * This plugin is invoked automaticaly. If the httpRequest has a "editItem", this will generate a FormSet with
 * values that will initialize the form elements. Otherwise, it will generate an empty FormSet
 */
public class editItem extends FortunataPlugin implements WikiPlugin {
    private static Logger log = Logger.getLogger( editItem.class );
    private OntModel m;

    public String execute (WikiContext context, Map parameterMap) throws PluginException {
        try{
            StringBuffer sb = new StringBuffer();
            String uniqueID = context.getHttpRequest().getParameter(Vpoet.HttpRequestParameter_EditElement);
            Vpoet vpoet = new Vpoet();
            String URI = vpoet.getURI();
            if (uniqueID != null){
               Individual indiv = getIndividual(context, uniqueID);
               sb.append("[{FormSet form='VPForm' ");
               sb.append(getInputNameValuePair ("designID", indiv, URI + Vpoet.propNameDesignID));
               sb.append(getInputNameValuePair ("elem", indiv, URI + Vpoet.propNameOntoElemID));
               sb.append(getInputNameValuePair ("id", indiv, URI + Vpoet.propNameProviderID));
               sb.append(" csscode='"  + textAreaFormat(indiv.getPropertyValue(m.getProperty(URI + Vpoet.propNameCSSCode)).toString()) +  "'" );
               sb.append(" jscode='"   + textAreaFormat(indiv.getPropertyValue(m.getProperty(URI + Vpoet.propNameJSCode)).toString()) +  "'" );
               sb.append(" htmlcode='" + textAreaFormat(indiv.getPropertyValue(m.getProperty(URI + Vpoet.propNameHTMLCode)).toString()) + "'" );
               sb.append(getInputNameValuePair ("designType", indiv, URI + Vpoet.propNameDesignType));
               sb.append(getInputNameValuePair ("selStyle1", indiv, URI + Vpoet.propNameStyle1));
               sb.append(getInputNameValuePair ("selColour1", indiv, URI + Vpoet.propNameForeColor1));
               sb.append(getInputNameValuePair ("selBack1", indiv, URI + Vpoet.propNameBackgColor1));
               sb.append(getInputNameValuePair ("selStyle2", indiv, URI + Vpoet.propNameStyle2));
               sb.append(getInputNameValuePair ("selColour2", indiv, URI + Vpoet.propNameForeColor2));
               sb.append(getInputNameValuePair ("selBack2", indiv, URI + Vpoet.propNameBackgColor2));
               sb.append(getInputNameValuePair ("userSTD", indiv, URI + Vpoet.propNameUserSTD));
               sb.append(getInputNameValuePair ("userRVS", indiv, URI + Vpoet.propNameUserRVS));
               sb.append(getInputNameValuePair ("colorBlind", indiv, URI + Vpoet.propNameColorBlind));
               sb.append(getInputNameValuePair ("policySize", indiv, URI + Vpoet.propNamePolicySize));
               sb.append(getInputNameValuePair ("policyResize", indiv, URI + Vpoet.propNamePolicyResize));
               sb.append("}] \n");
            }else {
               sb.append("[{FormSet form='VPForm'}] \n");
            }
            //System.out.println(sb.toString());
            return renderWikiText(context, sb.toString());
        }catch(PluginException e){
            //Shows a nice red alert with the message.
            throw new PluginException(renderWikiText(context, e.getMessage()));
        }catch(Throwable t){
            String msg="%%error" + wnl + t.getMessage() + wnl + "%%";
            throw new PluginException(renderWikiText(context, msg));
        }
    }
    private String getInputNameValuePair(String inputName, Individual indiv, String propName){
        RDFNode propValue = indiv.getPropertyValue(m.getProperty(propName));
        String propString = (propValue == null)? "" : propValue.toString();

        return inputName + "='"  + propString + "'" ;

    }
    private Individual getIndividual(WikiContext context, String elem)  throws PluginException{
        Vpoet vpoet = new Vpoet();
        //Ensure definitions file exists
        vpoet.createDataModelFileIfNeeded(context);
        //Ensure individuals file exists
        vpoet.createIndividualsFileIfNeeded(context);

        //Creates an empty model
        m = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM_RDFS_INF, null);
        //Reads Ontology
        vpoet.readSWAppModel(m, context);

        Individual indiv = m.getIndividual(vpoet.getURI() + elem);
        return indiv;
    }

    /**
     * Converts the initial String to the format required by a JSPWiki textArea initializer.
     * 1.- converts any newline (\n or \r) to '\' + 'n'. This can be error prone... :-( but it is the
     * solution adopted to the problem of initializing a textarea in a FormSet
     * 2.- A problem found is to insert the sentence "<textarea>whatever</textarea>. The '<' is alredy escaped to "&lt;"
     * by Jenna. However the '>' is not escaped. This is implemented by this method.
     * 3.- Another problem is single quotes('), that conflicts with the FormSet parameters mechanism. To avoid
     * this problem, sigle quotes are chnaged by its HTML escape code : &#39;   See http://www.dragonwinds.com/resources/html-codes.shtml
     * Maybe more translations to HTML escaped codes will be required :( 
     * @param iStr
     * @return
     */
    private static String textAreaFormat(String iStr){
         //String tmp =  iStr.replaceAll("[\n\r]", "\\n"); //Any \n or \r character is converted to the string "\\n"
         StringBuffer sb = new StringBuffer ();
         char c;
         for (int i = 0; i < iStr.length(); i++){
            c = iStr.charAt(i);
            switch(c){
                case '\n':          //Any occurrence of newlines is converted to '\' + 'n'
                case '\r':
                   sb.append("\\n");
                   break;
                case '>':
                   sb.append("&gt;"); //Any occurrence of '>' is converted to "&gt;"
                   break;
                case '\'':
                   sb.append("&#39;"); //Any occurrence of ' is converted to its HTML code (&#39;)
                   break;
                default:
                   sb.append(c);
                   break;
            }

           /* if (c == '\n'|| c == '\r'){   //Any occurrence of newlines is converted to '\' + 'n'
               sb.append("\\n");
            }else{
               if (c == '>'){
                   sb.append("&gt;");  //Any occurrence of '>' is converted to "&gt;"
               }else{
                   sb.append(c);
               }
            }*/
         }
         return sb.toString();
    }

    public static void main(String[] args){

        String[] tests = {
                     "line1\nline2\n>",
                     "\n>",
                     "line1\n>line2\r",
                     "\r",
                   };
        for (int i = 0; i < tests.length; i++){
           System.out.println("Test #" + i + ":'" + tests[i] + "'-->'" + textAreaFormat(tests[i]) + "'");
        }
    }
}
